package hnx.ca.security;
import hnx.ca.entity.VerifyXmlResult;
import hnx.ca.util.CRLVerifier;
import hnx.ca.util.CertificateVerificationException;
import hnx.ca.util.ErrorCodes;
import hnx.ca.util.ErrorMessages;
import hnx.ca.xml.verifier.OOXMLSignatureVerifier;

import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.util.List;

import org.apache.commons.lang3.StringUtils;


public class XMLVerifier {
	@SuppressWarnings("unchecked")
	public static VerifyXmlResult verifyXML(String fileName){
		int errorCode; 
		String serial = "";
		String errorMessage = "";
		try{
			OOXMLSignatureVerifier verifier = new OOXMLSignatureVerifier();
			CertPath certPath = verifier.getCertPathXML(fileName);
			if (certPath != null) {
				boolean verifySignature = verifier.verifySignatureXML(fileName);
				if (!verifySignature) {
					errorCode = ErrorCodes.VERIFY_XML.INVALID_CERTIFICATE;
				} else {
					@SuppressWarnings("rawtypes")
					List certsInChain = certPath.getCertificates();
					X509Certificate mCertificate = null;
					X509Certificate[] mCertChain = null;
					mCertChain = (X509Certificate[]) certsInChain.toArray(new X509Certificate[0]);
					mCertificate = mCertChain[0];
					
					Boolean checkCA2Certificate = verifyNacencomm(mCertificate);
					if(!checkCA2Certificate){
						errorCode = ErrorCodes.VERIFY_XML.CA_NOT_SUPPORT;
					}else{
						Boolean checkRevocationList = verifyCRL(mCertificate);
						if (!checkRevocationList) {
							errorCode = ErrorCodes.VERIFY_XML.CHECK_CRL_FAIL;
						}else{
							errorCode = ErrorCodes.VERIFY_XML.VALID_SIGNATURE;
							serial = getSerialNumber(mCertificate);	
						}
					}
				}
			} else {
				errorCode = ErrorCodes.VERIFY_XML.NO_CERTIFICATE_FOUND;
			}
		}
		catch (IOException ioe){
			errorCode = ErrorCodes.VERIFY_XML.FILE_NOT_FOUND;
		}
		catch (Exception e) {
			errorCode = ErrorCodes.VERIFY_XML.OTHER_EXCEPTION;
		}
		errorMessage = getErrorMessage(errorCode);
		return new VerifyXmlResult(errorCode, errorMessage, fileName, serial);
	}
	
	public static Boolean verifyNacencomm(X509Certificate mCertificate) {
		if(mCertificate == null){return false;}
		String issuer = mCertificate.getIssuerDN().toString();
		if(StringUtils.isEmpty(issuer)){return false;}		
		if (issuer.contains("CA2")) {return true;}
		return false;
	}

	public static boolean verifyCRL(X509Certificate cert) {		
		/*try {
			CRLVerifier.verifyCertificateCRLs(cert);
		} catch (CertificateVerificationException e) {
			return false;
		}*/		 
		return true;
	}
	
	public static void main(String args[]){
		try {
			VerifyXmlResult veri = verifyXML("D:\\test_sign.xml");
			System.out.println(veri.getErrorCode());
			System.out.println(veri.getErrorMessage());
			System.out.println(veri.getSerial());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static String getSerialNumber(X509Certificate cert){
		BigInteger serialNumber =  cert.getSerialNumber();
		if(serialNumber != null){
			return serialNumber.toString(16);
		}else{
			return "";
		}
	}
	
	public static String getErrorMessage(int errorCode){
		if(errorCode == ErrorCodes.VERIFY_XML.VALID_SIGNATURE){
			return ErrorMessages.VERIFY_XML.VALID_SIGNATURE;
		}
		else if(errorCode == ErrorCodes.VERIFY_XML.NO_SIGNATURE_FOUND){
			return ErrorMessages.VERIFY_XML.NO_SIGNATURE_FOUND;
		}
		else if(errorCode == ErrorCodes.VERIFY_XML.SIGNATURE_VERIFY_FAIL){
			return ErrorMessages.VERIFY_XML.SIGNATURE_VERIFY_FAIL;
		}
		else if(errorCode == ErrorCodes.VERIFY_XML.FILE_NOT_FOUND){
			return ErrorMessages.VERIFY_XML.FILE_NOT_FOUND;
		}
		else if(errorCode == ErrorCodes.VERIFY_XML.CHECK_CRL_FAIL){
			return ErrorMessages.VERIFY_XML.CHECK_CRL_FAIL;
		}
		else if(errorCode == ErrorCodes.VERIFY_XML.CA_NOT_SUPPORT){
			return ErrorMessages.VERIFY_XML.CA_NOT_SUPPORT;
		}
		else 
			return ErrorMessages.VERIFY_XML.OTHER_EXCEPTION;
	}
}
